
/*
This file is part of MJIN2.

Copyright (C) 2012-2013 Opensource Game Studio

This software is provided 'as-is', without any express or implied
warranty.  In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
   claim that you wrote the original software. If you use this software
   in a product, an acknowledgment in the product documentation would be
   appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

#include <mjin2/Common.h>

#include <mjin2/priv/Common.h>

#include <osg/GLExtensions>
#include <osg/Texture3D>

#include <sys/stat.h>

// Several GL_MAX defines for MinGW.
#ifdef WIN32
    #define GL_MAX_ELEMENTS_VERTICES          0x80E8
    #define GL_MAX_ELEMENTS_INDICES           0x80E9
    #define GL_MAX_CONVOLUTION_WIDTH          0x801A
    #define GL_MAX_CONVOLUTION_HEIGHT         0x801B
    #define GL_MAX_COLOR_MATRIX_STACK_DEPTH   0x80B3
    #define GL_MAX_TEXTURE_LOD_BIAS           0x84FD
    #define GL_MAX_CLIP_DISTANCES             0x0D32
    #define GL_MAX_ARRAY_TEXTURE_LAYERS       0x88FF
    #define GL_MAX_VARYING_COMPONENTS         0x8B4B
    #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
    #define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
    #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
    #define GL_MAX_RENDERBUFFER_SIZE          0x84E8
    #define GL_MAX_COLOR_ATTACHMENTS          0x8CDF
    #define GL_MAX_SAMPLES                    0x8D57
    #define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
    #define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
    #define GL_MAX_GEOMETRY_OUTPUT_VERTICES   0x8DE0
    #define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
    #define GL_MAX_VERTEX_OUTPUT_COMPONENTS   0x9122
    #define GL_MAX_GEOMETRY_INPUT_COMPONENTS  0x9123
    #define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
    #define GL_MAX_FRAGMENT_INPUT_COMPONENTS  0x9125
    #define GL_MAX_SERVER_WAIT_TIMEOUT        0x9111
    #define GL_MAX_SAMPLE_MASK_WORDS          0x8E59
    #define GL_MAX_COLOR_TEXTURE_SAMPLES      0x910E
    #define GL_MAX_DEPTH_TEXTURE_SAMPLES      0x910F
    #define GL_MAX_INTEGER_SAMPLES            0x9110
    #define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS   0x88FC
    #define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
    #define GL_MAX_VERTEX_STREAMS             0x8E71
    #define GL_MAX_SUBROUTINES                0x8DE7
    #define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8
    #define GL_MAX_PATCH_VERTICES             0x8E7D
    #define GL_MAX_TESS_GEN_LEVEL             0x8E7E
    #define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
    #define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
    #define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
    #define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
    #define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
    #define GL_MAX_TESS_PATCH_COMPONENTS      0x8E84
    #define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
    #define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
    #define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
    #define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
    #define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
    #define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
    #define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
    #define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
    #define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
    #define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
    #define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
    #define GL_MAX_VERTEX_UNIFORM_VECTORS     0x8DFB
    #define GL_MAX_VARYING_VECTORS            0x8DFC
    #define GL_MAX_FRAGMENT_UNIFORM_VECTORS   0x8DFD
    #define GL_MAX_VIEWPORTS                  0x825B
    #define GL_MAX_ELEMENT_INDEX              0x8D6B
    #define GL_MAX_DEBUG_MESSAGE_LENGTH       0x9143
    #define GL_MAX_DEBUG_LOGGED_MESSAGES      0x9144
    #define GL_MAX_DEBUG_GROUP_STACK_DEPTH    0x826C
    #define GL_MAX_LABEL_LENGTH               0x82E8
    #define GL_MAX_UNIFORM_LOCATIONS          0x826E
    #define GL_MAX_FRAMEBUFFER_WIDTH          0x9315
    #define GL_MAX_FRAMEBUFFER_HEIGHT         0x9316
    #define GL_MAX_FRAMEBUFFER_LAYERS         0x9317
    #define GL_MAX_FRAMEBUFFER_SAMPLES        0x9318
    #define GL_MAX_WIDTH                      0x827E
    #define GL_MAX_HEIGHT                     0x827F
    #define GL_MAX_DEPTH                      0x8280
    #define GL_MAX_LAYERS                     0x8281
    #define GL_MAX_COMBINED_DIMENSIONS        0x8282
    #define GL_MAX_NAME_LENGTH                0x92F6
    #define GL_MAX_NUM_ACTIVE_VARIABLES       0x92F7
    #define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
    #define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
    #define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
    #define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
    #define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
    #define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
    #define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
    #define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
    #define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
    #define GL_MAX_SHADER_STORAGE_BLOCK_SIZE  0x90DE
    #define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS
    #define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
    #define GL_MAX_VERTEX_ATTRIB_BINDINGS     0x82DA
    #define GL_MAX_TEXTURE_UNITS_ARB          0x84E2
    #define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB  0x851C
    #define GL_MAX_VERTEX_UNITS_ARB           0x86A4
    #define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841
    #define GL_MAX_PALETTE_MATRICES_ARB       0x8842
    #define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E
    #define GL_MAX_PROGRAM_MATRICES_ARB       0x862F
    #define GL_MAX_VERTEX_ATTRIBS_ARB         0x8869
    #define GL_MAX_PROGRAM_INSTRUCTIONS_ARB   0x88A1
    #define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
    #define GL_MAX_PROGRAM_TEMPORARIES_ARB    0x88A5
    #define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
    #define GL_MAX_PROGRAM_PARAMETERS_ARB     0x88A9
    #define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
    #define GL_MAX_PROGRAM_ATTRIBS_ARB        0x88AD
    #define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
    #define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
    #define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
    #define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
    #define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
    #define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
    #define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
    #define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
    #define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
    #define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
    #define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
    #define GL_MAX_TEXTURE_COORDS_ARB         0x8871
    #define GL_MAX_TEXTURE_IMAGE_UNITS_ARB    0x8872
    #define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
    #define GL_MAX_VARYING_FLOATS_ARB         0x8B4B
    #define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
    #define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
    #define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
    #define GL_MAX_DRAW_BUFFERS_ARB           0x8824
    #define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
    #define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29
    #define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD
    #define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE
    #define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF
    #define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0
    #define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1
    #define GL_MAX_TEXTURE_BUFFER_SIZE_ARB    0x8C2B
    #define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F
    #define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB   0x9143
    #define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB  0x9144
    #define GL_MAX_3D_TEXTURE_SIZE_EXT        0x8073
    #define GL_MAX_CONVOLUTION_WIDTH_EXT      0x801A
    #define GL_MAX_CONVOLUTION_HEIGHT_EXT     0x801B
    #define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3
    #define GL_MAX_4D_TEXTURE_SIZE_SGIS       0x8138
    #define GL_MAX_CLIPMAP_DEPTH_SGIX         0x8177
    #define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178
    #define GL_MAX_FRAMEZOOM_FACTOR_SGIX      0x818D
    #define GL_MAX_DEFORMATION_ORDER_SGIX     0x8197
    #define GL_MAX_FOG_FUNC_POINTS_SGIS       0x812C
    #define GL_MAX_VERTEX_HINT_PGI            0x1A22D
    #define GL_MAX_FRAGMENT_LIGHTS_SGIX       0x8404
    #define GL_MAX_ACTIVE_LIGHTS_SGIX         0x8405
    #define GL_MAX_ELEMENTS_VERTICES_EXT      0x80E8
    #define GL_MAX_ELEMENTS_INDICES_EXT       0x80E9
    #define GL_MAX_ASYNC_TEX_IMAGE_SGIX       0x835F
    #define GL_MAX_ASYNC_DRAW_PIXELS_SGIX     0x8360
    #define GL_MAX_ASYNC_READ_PIXELS_SGIX     0x8361
    #define GL_MAX_ASYNC_HISTOGRAM_SGIX       0x832D
    #define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337
    #define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT  0x851C
    #define GL_MAX_TEXTURE_LOD_BIAS_EXT       0x84FD
    #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
    #define GL_MAX_SHININESS_NV               0x8504
    #define GL_MAX_SPOT_EXPONENT_NV           0x8505
    #define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520
    #define GL_MAX_GENERAL_COMBINERS_NV       0x854D
    #define GL_MAX_MAP_TESSELLATION_NV        0x86D6
    #define GL_MAX_RATIONAL_EVAL_ORDER_NV     0x86D7
    #define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV  0x84F8
    #define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E
    #define GL_MAX_TRACK_MATRICES_NV          0x862F
    #define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
    #define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5
    #define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6
    #define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7
    #define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8
    #define GL_MAX_VERTEX_SHADER_LOCALS_EXT   0x87C9
    #define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA
    #define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB
    #define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC
    #define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD
    #define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE
    #define GL_MAX_VERTEX_STREAMS_ATI         0x876B
    #define GL_MAX_DRAW_BUFFERS_ATI           0x8824
    #define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868
    #define GL_MAX_TEXTURE_COORDS_NV          0x8871
    #define GL_MAX_TEXTURE_IMAGE_UNITS_NV     0x8872
    #define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
    #define GL_MAX_PROGRAM_CALL_DEPTH_NV      0x88F5
    #define GL_MAX_PROGRAM_IF_DEPTH_NV        0x88F6
    #define GL_MAX_PROGRAM_LOOP_DEPTH_NV      0x88F7
    #define GL_MAX_PROGRAM_LOOP_COUNT_NV      0x88F8
    #define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908
    #define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909
    #define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5
    #define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6
    #define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27
    #define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28
    #define GL_MAX_TEXTURE_BUFFER_SIZE_EXT    0x8C2B
    #define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0
    #define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1
    #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80
    #define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A
    #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B
    #define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2
    #define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3
    #define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4
    #define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT  0x8DED
    #define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A
    #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B
    #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80
    #define GL_MAX_SAMPLE_MASK_WORDS_NV       0x8E59
    #define GL_MAX_SHADER_BUFFER_ADDRESS_NV   0x8F35
    #define GL_MAX_IMAGE_UNITS_EXT            0x8F38
    #define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39
    #define GL_MAX_IMAGE_SAMPLES_EXT          0x906D
    #define GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A
    #define GL_MAX_PROGRAM_SUBROUTINE_PARAMETERS_NV 0x8F44
    #define GL_MAX_PROGRAM_SUBROUTINE_NUM_NV  0x8F45
    #define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV   0x86D8
    #define GL_MAX_DEBUG_MESSAGE_LENGTH_AMD   0x9143
    #define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD  0x9144
    #define GL_MAX_SPARSE_TEXTURE_SIZE_AMD    0x9198
    #define GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD 0x9199
    #define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS 0x919A
#endif

namespace mjin2
{
namespace priv
{

s32 gl(GLenum name)
{
    s32 i;
    glGetIntegerv(name, &i);
    return i;
}

void makeSingleDir(const String &dir) throw (Exception)
{
#ifdef WIN32
    if (::mkdir(dir.c_str()) < 0)
#else
    if (::mkdir(dir.c_str(), 0755) < 0)
#endif
        MJIN2_EXCEPTION("Cannot create directory",
                        MJIN2_STR("mkdir(%s): %s", dir.c_str(), strerror(errno)));
}

VideoInfo videoInfo(const osg::GL2Extensions *extensions, u32 contextID)
{
    // TODO: Remove const_cast and updated to the latest OSG.
    osg::GL2Extensions *ext = const_cast<osg::GL2Extensions*>(extensions);
    VideoInfo vi;
    vi.glVersion  = reinterpret_cast<const char *>(glGetString(GL_VERSION));
    vi.glVendor   = reinterpret_cast<const char *>(glGetString(GL_VENDOR));
    vi.glRenderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
    float glVersion = ext->getGlVersion();
    if (glVersion >= 2.0)
        vi.glslVersion = reinterpret_cast<const char *>(
            glGetString(GL_SHADING_LANGUAGE_VERSION));
    else
        vi.glslVersion = "No GLSL for OpenGL 1\n";
    vi.glslSupported                = ext->isGlslSupported();
    vi.shaderObjectsSupported       = ext->isShaderObjectsSupported();
    vi.vertexShaderSupported        = ext->isVertexShaderSupported();
    vi.fragmentShaderSupported      = ext->isFragmentShaderSupported();
    vi.glsl100Supported             = ext->isLanguage100Supported();
    vi.geometryShader4Supported     = ext->isGeometryShader4Supported();
    vi.tessellationShadersSupported = ext->areTessellationShadersSupported();
    vi.gpuShader4Supported          = ext->isGpuShader4Supported();
    vi.uniformBufferObjectSupported = ext->isUniformBufferObjectSupported();
    vi.gpuShaderFp64Supported       = ext->isGpuShaderFp64Supported();
    vi.shaderAtomicCounterSupported = ext->isShaderAtomicCounterSupported();
    vi.gl12 = (glVersion >= 1.2);
    if (vi.gl12)
    {
        vi.gl12Max3DTextureSize    = gl(GL_MAX_3D_TEXTURE_SIZE);
        vi.gl12MaxElementsIndices  = gl(GL_MAX_ELEMENTS_INDICES);
        vi.gl12MaxElementsVertices = gl(GL_MAX_ELEMENTS_VERTICES);
    }
    vi.gl13 = (glVersion >= 1.3);
    if (vi.gl13)
    {
        vi.gl13MaxCubeMapTextureSize = gl(GL_MAX_CUBE_MAP_TEXTURE_SIZE);
        vi.gl13MaxTextureUnits       = gl(GL_MAX_TEXTURE_UNITS);
    }
    vi.gl14 = (glVersion >= 1.4);
    if (vi.gl14)
        vi.gl14MaxTextureLODBias = gl(GL_MAX_TEXTURE_LOD_BIAS);
    vi.gl20 = (glVersion >= 2.0);
    if (vi.gl20)
    {
        vi.gl20MaxDrawbuffers               = gl(GL_MAX_DRAW_BUFFERS);
        vi.gl20MaxVertexAttribs             = gl(GL_MAX_VERTEX_ATTRIBS);
        vi.gl20MaxTextureImageUnits         = gl(GL_MAX_TEXTURE_IMAGE_UNITS);
        vi.gl20MaxFragmentUniformComponents = gl(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS);
        vi.gl20MaxVertexUniformComponents   = gl(GL_MAX_VERTEX_UNIFORM_COMPONENTS);
        vi.gl20MaxVaryingFloats             = gl(GL_MAX_VARYING_FLOATS);
        vi.gl20MaxVertexTextureImageUnits   = gl(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
        vi.gl20MaxCombinedTextureImageUnits = gl(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
        vi.gl20MaxTextureCoords             = gl(GL_MAX_TEXTURE_COORDS);
    }
    vi.gl30 = (glVersion >= 3.0);
    if (vi.gl30)
    {
        vi.gl30MaxClipDistances                          = gl(GL_MAX_CLIP_DISTANCES);
        vi.gl30MaxArrayTextureLayers                     = gl(GL_MAX_ARRAY_TEXTURE_LAYERS);
        vi.gl30MaxVaryingComponents                      = gl(GL_MAX_VARYING_COMPONENTS);
        vi.gl30MaxTransformFeedbackSeparateComponents    = gl(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS);
        vi.gl30MaxTransformFeedbackInterleavedComponents = gl(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
        vi.gl30MaxTransformFeedbackSeparateAttribs       = gl(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
        vi.gl30MaxRenderbufferSize                       = gl(GL_MAX_RENDERBUFFER_SIZE);
        vi.gl30MaxColorAttachments                       = gl(GL_MAX_COLOR_ATTACHMENTS);
        vi.gl30MaxSamples                                = gl(GL_MAX_SAMPLES);
    }
    vi.gl31 = (glVersion >= 3.1);
    if (vi.gl31)
    {
        vi.gl31MaxTextureBufferSize                 = gl(GL_MAX_TEXTURE_BUFFER_SIZE);
        vi.gl31MaxRectangleTextureSize              = gl(GL_MAX_RECTANGLE_TEXTURE_SIZE);
        vi.gl31MaxVertexUniformBlocks               = gl(GL_MAX_VERTEX_UNIFORM_BLOCKS);
        vi.gl31MaxFragmentUniformBlocks             = gl(GL_MAX_FRAGMENT_UNIFORM_BLOCKS);
        vi.gl31MaxCombinedUniformBlocks             = gl(GL_MAX_COMBINED_UNIFORM_BLOCKS);
        vi.gl31MaxUniformBufferBindings             = gl(GL_MAX_UNIFORM_BUFFER_BINDINGS);
        vi.gl31MaxUniformBlockSize                  = gl(GL_MAX_UNIFORM_BLOCK_SIZE);
        vi.gl31MaxCombinedVertexUniformComponents   = gl(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS);
        vi.gl31MaxCombinedFragmentUniformComponents = gl(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS);
    }
    vi.gl32 = (glVersion >= 3.2);
    if (vi.gl32)
    {
        vi.gl32MaxGeometryTextureImageUnits     = gl(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS);
        vi.gl32MaxGeometryUniformComponents     = gl(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS);
        vi.gl32MaxGeometryOutputVertices        = gl(GL_MAX_GEOMETRY_OUTPUT_VERTICES);
        vi.gl32MaxGeometryTotalOutputComponents = gl(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS);
        vi.gl32MaxVertexOutputComponents        = gl(GL_MAX_VERTEX_OUTPUT_COMPONENTS);
        vi.gl32MaxGeometryInputComponents       = gl(GL_MAX_GEOMETRY_INPUT_COMPONENTS);
        vi.gl32MaxGeometryOutputComponents      = gl(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS);
        vi.gl32MaxFragmentInputComponets        = gl(GL_MAX_FRAGMENT_INPUT_COMPONENTS);
        vi.gl32MaxVaryingComponets              = gl(GL_MAX_VARYING_COMPONENTS);
        vi.gl32MaxServerWaitTimeout             = gl(GL_MAX_SERVER_WAIT_TIMEOUT);
        vi.gl32MaxSampleMaskWords               = gl(GL_MAX_SAMPLE_MASK_WORDS);
        vi.gl32MaxColorTextureSamples           = gl(GL_MAX_COLOR_TEXTURE_SAMPLES);
        vi.gl32MaxDepthTextureSamples           = gl(GL_MAX_DEPTH_TEXTURE_SAMPLES);
        vi.gl32MaxIntegerSamples                = gl(GL_MAX_INTEGER_SAMPLES);
    }
    vi.gl33 = (glVersion >= 3.3);
    if (vi.gl33)
        vi.gl33MaxDualSourceDrawbuffers = gl(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS);

    vi.gl40 = (glVersion >= 4.0);
    if (vi.gl40)
    {
        vi.gl40MaxGeometryShaderInvocations               = gl(GL_MAX_GEOMETRY_SHADER_INVOCATIONS);
        vi.gl40MaxVertexStreams                           = gl(GL_MAX_VERTEX_STREAMS);
        vi.gl40MaxSubroutines                             = gl(GL_MAX_SUBROUTINES);
        vi.gl40MaxSubroutineUniformLocations              = gl(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS);
        vi.gl40MaxPatchVertices                           = gl(GL_MAX_PATCH_VERTICES);
        vi.gl40MaxTessGenLevel                            = gl(GL_MAX_TESS_GEN_LEVEL);
        vi.gl40MaxTessControlUniformComponents            = gl(GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS);
        vi.gl40MaxTessEvaluationUniformComponents         = gl(GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS);
        vi.gl40MaxTessControlTextureImageUnits            = gl(GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS);
        vi.gl40MaxTessEvaluationTextureImageUnits         = gl(GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS);
        vi.gl40MaxTessControlOutputComponents             = gl(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS);
        vi.gl40MaxTessPatchComponents                     = gl(GL_MAX_TESS_PATCH_COMPONENTS);
        vi.gl40MaxTessControlTotalOutputComponents        = gl(GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS);
        vi.gl40MaxTessEvaluationOutputComponents          = gl(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS);
        vi.gl40MaxTessControlUniformBlocks                = gl(GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS);
        vi.gl40MaxTessEvaluationUniformBlocks             = gl(GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS);
        vi.gl40MaxTessControlInputComponents              = gl(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS);
        vi.gl40MaxTessEvaluationInputComponents           = gl(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS);
        vi.gl40MaxCombinedTessControlUniformComponents    = gl(GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS);
        vi.gl40MaxCombinedTessEvaluationUniformComponents = gl(GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS);
        vi.gl40MaxTransformFeedbackBuffers                = gl(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS);
    }
    vi.gl41 = (glVersion >= 4.1);
    if (vi.gl41)
    {
        vi.gl41MaxVertexUniformVectors   = gl(GL_MAX_VERTEX_UNIFORM_VECTORS);
        vi.gl41MaxVaryingVectors         = gl(GL_MAX_VARYING_VECTORS);
        vi.gl41MaxFragmentUniformVectors = gl(GL_MAX_FRAGMENT_UNIFORM_VECTORS);
        vi.gl41MaxViewports              = gl(GL_MAX_VIEWPORTS);
    }
    vi.gl42 = (glVersion >= 4.2);
    if (vi.gl42)
    {
        vi.gl42MaxVertexAtomicCounterBuffers           = gl(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS);
        vi.gl42MaxTessControlAtomicCounterBuffers      = gl(GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS);
        vi.gl42MaxTessEvaluationAtomicCounterBuffers   = gl(GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS);
        vi.gl42MaxGeometryAtomicCounterBuffers         = gl(GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS);
        vi.gl42MaxFragmentAtomicCounterBuffers         = gl(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS);
        vi.gl42MaxCombinedAtomicCounterBuffers         = gl(GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS);
        vi.gl42MaxVetexAtomicCounters                  = gl(GL_MAX_VERTEX_ATOMIC_COUNTERS);
        vi.gl42MaxTessControlAtomicCounters            = gl(GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS);
        vi.gl42MaxTessEvaluationAtomicCounters         = gl(GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS);
        vi.gl42MaxGeometryAtomicCounters               = gl(GL_MAX_GEOMETRY_ATOMIC_COUNTERS);
        vi.gl42MaxFragmentAtomicCounters               = gl(GL_MAX_FRAGMENT_ATOMIC_COUNTERS);
        vi.gl42MaxCombinedAtomicCounters               = gl(GL_MAX_COMBINED_ATOMIC_COUNTERS);
        vi.gl42MaxAtomicCounterBufferSize              = gl(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE);
        vi.gl42MaxAtomicCounterBufferBindings          = gl(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS);
        vi.gl42MaxImageUnits                           = gl(GL_MAX_IMAGE_UNITS);
        vi.gl42MaxCombinedImageUnitsAndFragmentOutputs = gl(GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS);
        vi.gl42MaxImageSamples                         = gl(GL_MAX_IMAGE_SAMPLES);
        vi.gl42MaxVertexImageUniforms                  = gl(GL_MAX_VERTEX_IMAGE_UNIFORMS);
        vi.gl42MaxTessControlImageUniforms             = gl(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS);
        vi.gl42MaxTessEvaluationImageUniforms          = gl(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS);
        vi.gl42MaxGeometryImageUniforms                = gl(GL_MAX_GEOMETRY_IMAGE_UNIFORMS);
        vi.gl42MaxFragmentImageUniforms                = gl(GL_MAX_FRAGMENT_IMAGE_UNIFORMS);
        vi.gl42MaxCombinedImageUniforms                = gl(GL_MAX_COMBINED_IMAGE_UNIFORMS);
    }
    vi.gl43 = (glVersion >= 4.3);
    if (vi.gl43)
    {
        vi.gl43MaxElementIndex                      = gl(GL_MAX_ELEMENT_INDEX);
        vi.gl43MaxComputeUniformBlocks              = gl(GL_MAX_COMPUTE_UNIFORM_BLOCKS);
        vi.gl43MaxComputeTextureImageUnits          = gl(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS);
        vi.gl43MaxComputeImageUniforms              = gl(GL_MAX_COMPUTE_IMAGE_UNIFORMS);
        vi.gl43MaxComputeSharedMemorySize           = gl(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE);
        vi.gl43MaxComputeUniformComponents          = gl(GL_MAX_COMPUTE_UNIFORM_COMPONENTS);
        vi.gl43MaxComputeAtomicCounterBuffers       = gl(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS);
        vi.gl43MaxComputeAtomicCounters             = gl(GL_MAX_COMPUTE_ATOMIC_COUNTERS);
        vi.gl43MaxCombinedComputeUniformComponents  = gl(GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS);
        vi.gl43MaxComputeLocalInvocations           = gl(GL_MAX_COMPUTE_LOCAL_INVOCATIONS);
        vi.gl43MaxComputeWorkGroupCount             = gl(GL_MAX_COMPUTE_WORK_GROUP_COUNT);
        vi.gl43MaxComputeWorkGroupSize              = gl(GL_MAX_COMPUTE_WORK_GROUP_SIZE);
        vi.gl43MaxDebugMessageLength                = gl(GL_MAX_DEBUG_MESSAGE_LENGTH);
        vi.gl43MaxDebugLoggedMessages               = gl(GL_MAX_DEBUG_LOGGED_MESSAGES);
        vi.gl43MaxDebugGroupStackDepth              = gl(GL_MAX_DEBUG_GROUP_STACK_DEPTH);
        vi.gl43MaxLabelLength                       = gl(GL_MAX_LABEL_LENGTH);
        vi.gl43MaxUniformLocations                  = gl(GL_MAX_UNIFORM_LOCATIONS);
        vi.gl43MaxFrameBufferWidth                  = gl(GL_MAX_FRAMEBUFFER_WIDTH);
        vi.gl43MaxFrameBufferHeight                 = gl(GL_MAX_FRAMEBUFFER_HEIGHT);
        vi.gl43MaxFrameBufferLayers                 = gl(GL_MAX_FRAMEBUFFER_LAYERS);
        vi.gl43MaxFrameBufferSamples                = gl(GL_MAX_FRAMEBUFFER_SAMPLES);
        vi.gl43MaxWidth                             = gl(GL_MAX_WIDTH);
        vi.gl43MaxHeight                            = gl(GL_MAX_HEIGHT);
        vi.gl43MaxDepth                             = gl(GL_MAX_DEPTH);
        vi.gl43MaxLayers                            = gl(GL_MAX_LAYERS);
        vi.gl43MaxCombinedDimensions                = gl(GL_MAX_COMBINED_DIMENSIONS);
        vi.gl43MaxNameLength                        = gl(GL_MAX_NAME_LENGTH);
        vi.gl43MaxNumActiveVariables                = gl(GL_MAX_NUM_ACTIVE_VARIABLES);
        vi.gl43MaxNumCompatibleSubroutines          = gl(GL_MAX_NUM_COMPATIBLE_SUBROUTINES);
        vi.gl43MaxVertexShaderStorageBlocks         = gl(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS);
        vi.gl43MaxGeometryShaderStorageBlocks       = gl(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS);
        vi.gl43MaxTessControlShaderStorageBlocks    = gl(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS);
        vi.gl43MaxTessEvaluationShaderStorageBlocks = gl(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS);
        vi.gl43MaxFragmentShaderStorageBlocks       = gl(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS);
        vi.gl43MaxComputeShaderStorageBlocks        = gl(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS);
        vi.gl43MaxCombinedShaderStorageBlocks       = gl(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS);
        vi.gl43MaxShaderStorageBufferBindings       = gl(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
        vi.gl43MaxShaderStorageBlockSize            = gl(GL_MAX_SHADER_STORAGE_BLOCK_SIZE);
        vi.gl43MaxCombinedShaderOutputResources     = gl(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES);
        vi.gl43MaxVertexAttribRelativeOffset        = gl(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET);
        vi.gl43MaxVertexAttribBindings              = gl(GL_MAX_VERTEX_ATTRIB_BINDINGS);
    }
    vi.arbImaging = osg::isGLExtensionSupported(contextID, "GL_ARB_imaging");
    if (vi.arbImaging)
    {
        vi.arbImagingMaxConvolutionWidth      = gl(GL_MAX_CONVOLUTION_WIDTH);
        vi.arbImagingMaxConvolutionHeight     = gl(GL_MAX_CONVOLUTION_HEIGHT);
        vi.arbImagingMaxColorMatrixStackDepth = gl(GL_MAX_COLOR_MATRIX_STACK_DEPTH);
    }
    vi.arbMultitexture = osg::isGLExtensionSupported(contextID, "GL_ARB_multitexture");
    if (vi.arbMultitexture)
        vi.arbMultitextureMaxTextureUnitsARB = gl(GL_MAX_TEXTURE_UNITS_ARB);
    vi.arbTextureCubeMap = osg::isGLExtensionSupported(contextID, "GL_ARB_texture_cube_map");
    if (vi.arbTextureCubeMap)
        vi.arbTextureCubeMapMaxCubeMapTextureSizeARB = gl(GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB);
    vi.arbVertexBlend = osg::isGLExtensionSupported(contextID, "GL_ARB_vertex_blend");
    if (vi.arbVertexBlend)
        vi.arbVertexBlendMaxVertexUnitsARB = gl(GL_MAX_VERTEX_UNITS_ARB);
    vi.arbMatrixPalette = osg::isGLExtensionSupported(contextID, "GL_ARB_matrix_palette");
    if (vi.arbMatrixPalette)
    {
        vi.arbMatrixPaletteMaxMatrixPaletteStackDepthARB = gl(GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB);
        vi.arbMatrixPaletteMaxPaletteMatricesARB         = gl(GL_MAX_PALETTE_MATRICES_ARB);
    }
    vi.arbVertexProgram = osg::isGLExtensionSupported(contextID, "GL_ARB_vertex_program");
    if (vi.arbVertexProgram)
    {
        vi.arbVertexProgramMaxProgramMatrixStackDepthARB       = gl(GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB);
        vi.arbVertexProgramMaxProgramMatricesARB               = gl(GL_MAX_PROGRAM_MATRICES_ARB);
        vi.arbVertexProgramMaxVertexAttribsARB                 = gl(GL_MAX_VERTEX_ATTRIBS_ARB);
        vi.arbVertexProgramMaxProgramInstructionsARB           = gl(GL_MAX_PROGRAM_INSTRUCTIONS_ARB);
        vi.arbVertexProgramMaxProgramNativeInstructionsARB     = gl(GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB);
        vi.arbVertexProgramMaxProgramTemporariesARB            = gl(GL_MAX_PROGRAM_TEMPORARIES_ARB);
        vi.arbVertexProgramMaxProgramNativeTemporariesARB      = gl(GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB);
        vi.arbVertexProgramMaxProgramParametersARB             = gl(GL_MAX_PROGRAM_PARAMETERS_ARB);
        vi.arbVertexProgramMaxProgramNativeParametersARB       = gl(GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB);
        vi.arbVertexProgramMaxProgramAttribsARB                = gl(GL_MAX_PROGRAM_ATTRIBS_ARB);
        vi.arbVertexProgramMaxProgramNativeAttribsARB          = gl(GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB);
        vi.arbVertexProgramMaxProgramAddressRegistersARB       = gl(GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB);
        vi.arbVertexProgramMaxProgramNativeAddressRegistersARB = gl(GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB);
        vi.arbVertexProgramMaxProgramLocalParametersARB        = gl(GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
        vi.arbVertexProgramMaxProgramEnvParametersARB          = gl(GL_MAX_PROGRAM_ENV_PARAMETERS_ARB);
    }
    vi.arbFragmentProgram = osg::isGLExtensionSupported(contextID, "GL_ARB_fragment_program");
    if (vi.arbFragmentProgram)
    {
        vi.arbFragmentProgramMaxProgramAluInstructionsARB       = gl(GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB);
        vi.arbFragmentProgramMaxProgramTexInstructionsARB       = gl(GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB);
        vi.arbFragmentProgramMaxProgramTexIndirectionsARB       = gl(GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB);
        vi.arbFragmentProgramMaxProgramNativeAluInstructionsARB = gl(GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB);
        vi.arbFragmentProgramMaxProgramNativeTexInstructionsARB = gl(GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB);
        vi.arbFragmentProgramMaxProgramNativeTexIndirectionsARB = gl(GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB);
        vi.arbFragmentProgramMaxTextureCoordsARB                = gl(GL_MAX_TEXTURE_COORDS_ARB);
        vi.arbFragmentProgramMaxTextureImageUnitsARB            = gl(GL_MAX_TEXTURE_IMAGE_UNITS_ARB);
    }
    vi.arbVertexShader = osg::isGLExtensionSupported(contextID, "GL_ARB_vertex_shader");
    if (vi.arbVertexShader)
    {
        vi.arbVertexShaderMaxVertexUniformComponentsARB   = gl(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB);
        vi.arbVertexShaderMaxVaryingFloatsARB             = gl(GL_MAX_VARYING_FLOATS_ARB);
        vi.arbVertexShaderMaxVertexTextureImageUnitsARB   = gl(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB);
        vi.arbVertexShaderMaxCombinedTextureImageUnitsARB = gl(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB);
    }
    vi.arbFragmentShader = osg::isGLExtensionSupported(contextID, "GL_ARB_fragment_shader");
    if (vi.arbFragmentShader)
        vi.arbFragmentShaderMaxFragmentUniformComponentsARB = gl(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB);
    vi.arbDrawbuffers = osg::isGLExtensionSupported(contextID, "GL_ARB_draw_buffers");
    if (vi.arbDrawbuffers)
        vi.arbDrawbuffersMaxDrawbuffersARB = gl(GL_MAX_DRAW_BUFFERS_ARB);
    vi.arbTextureRectangle = osg::isGLExtensionSupported(contextID, "GL_ARB_texture_rectangle");
    if (vi.arbTextureRectangle)
        vi.arbTextureRectangleMaxRectangleTextureSizeARB = gl(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB);
    vi.arbFramebufferObject = osg::isGLExtensionSupported(contextID, "GL_ARB_framebuffer_object");
    if (vi.arbFramebufferObject)
    {
        vi.arbFramebufferObjectMaxRenderbufferSize = gl(GL_MAX_RENDERBUFFER_SIZE);
        vi.arbFramebufferObjectMaxColorAttachments = gl(GL_MAX_COLOR_ATTACHMENTS);
        vi.arbFramebufferObjectMaxSamples          = gl(GL_MAX_SAMPLES);
    }
    vi.arbGeometryShader4 = osg::isGLExtensionSupported(contextID, "GL_ARB_geometry_shader4");
    if (vi.arbGeometryShader4)
    {
        vi.arbGeometryShader4MaxGeometryTextureImageUnitsARB     = gl(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB);
        vi.arbGeometryShader4MaxGeometryVaryingComponentsARB     = gl(GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB);
        vi.arbGeometryShader4MaxVertexVaryingComponentsARB       = gl(GL_MAX_VERTEX_VARYING_COMPONENTS_ARB);
        vi.arbGeometryShader4MaxGeometryUniformComponentsARB     = gl(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB);
        vi.arbGeometryShader4MaxGeometryOutputVerticesARB        = gl(GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB);
        vi.arbGeometryShader4MaxGeometryTotalOutputComponentsARB = gl(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB);
    }
    vi.arbTextureBufferObject = osg::isGLExtensionSupported(contextID, "GL_ARB_texture_buffer_object");
    if (vi.arbTextureBufferObject)
        vi.arbTextureBufferObjectMaxTextureBufferSizeARB = gl(GL_MAX_TEXTURE_BUFFER_SIZE_ARB);
    vi.arbUniformBufferObject = osg::isGLExtensionSupported(contextID, "GL_ARB_uniform_buffer_object");
    if (vi.arbUniformBufferObject)
    {
        vi.arbUniformBufferObjectMaxVertexUniformBlocks               = gl(GL_MAX_VERTEX_UNIFORM_BLOCKS);
        vi.arbUniformBufferObjectMaxGeometryUniformBlocks             = gl(GL_MAX_GEOMETRY_UNIFORM_BLOCKS);
        vi.arbUniformBufferObjectMaxFragmentUniformBlocks             = gl(GL_MAX_FRAGMENT_UNIFORM_BLOCKS);
        vi.arbUniformBufferObjectMaxCombinedUniformBlocks             = gl(GL_MAX_COMBINED_UNIFORM_BLOCKS);
        vi.arbUniformBufferObjectMaxUniformBufferBindings             = gl(GL_MAX_UNIFORM_BUFFER_BINDINGS);
        vi.arbUniformBufferObjectMaxUniformBlockSize                  = gl(GL_MAX_UNIFORM_BLOCK_SIZE);
        vi.arbUniformBufferObjectMaxCombinedVertexUniformComponents   = gl(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS);
        vi.arbUniformBufferObjectMaxCombinedGeometryUniformComponents = gl(GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS);
        vi.arbUniformBufferObjectMaxCombinedFragmentUniformComponents = gl(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS);
    }
    vi.arbSync = osg::isGLExtensionSupported(contextID, "GL_ARB_sync");
    if (vi.arbSync)
        vi.arbSyncMaxServerWaitTimeout = gl(GL_MAX_SERVER_WAIT_TIMEOUT);
    vi.arbTextureMultisample = osg::isGLExtensionSupported(contextID, "GL_ARB_texture_multisample");
    if (vi.arbTextureMultisample)
    {
        vi.arbTextureMultisampleMaxSampleMaskWords     = gl(GL_MAX_SAMPLE_MASK_WORDS);
        vi.arbTextureMultisampleMaxColorTextureSamples = gl(GL_MAX_COLOR_TEXTURE_SAMPLES);
        vi.arbTextureMultisampleMaxDepthTextureSamples = gl(GL_MAX_DEPTH_TEXTURE_SAMPLES);
        vi.arbTextureMultisampleMaxIntegerSamples      = gl(GL_MAX_INTEGER_SAMPLES);
    }
    vi.arbTextureGather = osg::isGLExtensionSupported(contextID, "GL_ARB_texture_gather");
    if (vi.arbTextureGather)
        vi.arbTextureGatherMaxProgramTextureGatherComponentsARB = gl(GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB);
    vi.arbBlendFuncExtended = osg::isGLExtensionSupported(contextID, "GL_ARB_blend_func_extended");
    if (vi.arbBlendFuncExtended)
        vi.arbBlendFuncExtendedMaxDualSourceDrawBuffers = gl(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS);
    vi.arbGpuShader5 = osg::isGLExtensionSupported(contextID, "GL_ARB_gpu_shader5");
    if (vi.arbGpuShader5)
        vi.arbGpuShader5MaxGeometryShaderInvocations = gl(GL_MAX_GEOMETRY_SHADER_INVOCATIONS);
    vi.arbShaderSubroutine = osg::isGLExtensionSupported(contextID, "GL_ARB_shader_subroutine");
    if (vi.arbShaderSubroutine)
    {
        vi.arbShaderSubroutineMaxSubroutines                = gl(GL_MAX_SUBROUTINES);
        vi.arbShaderSubroutineMaxSubroutineUniformLocations = gl(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS);
    }
    vi.arbTessellationShader = osg::isGLExtensionSupported(contextID, "GL_ARB_tessellation_shader");
    if (vi.arbTessellationShader)
    {
        vi.arbTessellationShaderMaxPatchVertices                           = gl(GL_MAX_PATCH_VERTICES);
        vi.arbTessellationShaderMaxTessGenLevel                            = gl(GL_MAX_TESS_GEN_LEVEL);
        vi.arbTessellationShaderMaxTessControlUniformComponents            = gl(GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS);
        vi.arbTessellationShaderMaxTessEvaluationUniformComponents         = gl(GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS);
        vi.arbTessellationShaderMaxTessControlTextureImageUnits            = gl(GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS);
        vi.arbTessellationShaderMaxTessEvaluationTextureImageUnits         = gl(GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS);
        vi.arbTessellationShaderMaxTessControlOutputComponents             = gl(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS);
        vi.arbTessellationShaderMaxTessPatchComponents                     = gl(GL_MAX_TESS_PATCH_COMPONENTS);
        vi.arbTessellationShaderMaxTessControlTotalOutputComponents        = gl(GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS);
        vi.arbTessellationShaderMaxTessEvaluationOutputComponents          = gl(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS);
        vi.arbTessellationShaderMaxTessControlUniformBlocks                = gl(GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS);
        vi.arbTessellationShaderMaxTessEvaluationUniformBlocks             = gl(GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS);
        vi.arbTessellationShaderMaxTessControlInputComponents              = gl(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS);
        vi.arbTessellationShaderMaxTessEvaluationInputComponents           = gl(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS);
        vi.arbTessellationShaderMaxCombinedTessControlUniformComponents    = gl(GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS);
        vi.arbTessellationShaderMaxCombinedTessEvaluationUniformComponents = gl(GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS);
    }
    vi.arbTransformFeedback3 = osg::isGLExtensionSupported(contextID, "GL_ARB_transform_feedback3");
    if (vi.arbTransformFeedback3)
    {
        vi.arbTransformFeedback3MaxTransformFeedbackBuffers = gl(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS);
        vi.arbTransformFeedback3MaxVertexStreams            = gl(GL_MAX_VERTEX_STREAMS);
    }
    vi.arbES2Compatibility = osg::isGLExtensionSupported(contextID, "GL_ARB_ES2_compatibility");
    if (vi.arbES2Compatibility)
    {
        vi.arbES2CompatibilityMaxVertexUniformVectors   = gl(GL_MAX_VERTEX_UNIFORM_VECTORS);
        vi.arbES2CompatibilityMaxVaryingVectors         = gl(GL_MAX_VARYING_VECTORS);
        vi.arbES2CompatibilityMaxFragmentUniformVectors = gl(GL_MAX_FRAGMENT_UNIFORM_VECTORS);
    }
    vi.arbViewportArray = osg::isGLExtensionSupported(contextID, "GL_ARB_viewport_array");
    if (vi.arbViewportArray)
        vi.arbViewportArrayMaxViewports = gl(GL_MAX_VIEWPORTS);
    vi.arbDebugOutput = osg::isGLExtensionSupported(contextID, "GL_ARB_debug_output");
    if (vi.arbDebugOutput)
    {
        vi.arbDebugOutputMaxDebugMessageLengthARB  = gl(GL_MAX_DEBUG_MESSAGE_LENGTH_ARB);
        vi.arbDebugOutputMaxDebugLoggedMessagesARB = gl(GL_MAX_DEBUG_LOGGED_MESSAGES_ARB);
    }
    vi.arbShaderAtomicCounters = osg::isGLExtensionSupported(contextID, "GL_ARB_shader_atomic_counters");
    if (vi.arbShaderAtomicCounters)
    {
        vi.arbShaderAtomicCountersMaxVertexAtomicCounterBuffers         = gl(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS);
        vi.arbShaderAtomicCountersMaxTessControlAtomicCounterBuffers    = gl(GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS);
        vi.arbShaderAtomicCountersMaxTessEvaluationAtomicCounterBuffers = gl(GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS);
        vi.arbShaderAtomicCountersMaxGeometryAtomicCounterBuffers       = gl(GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS);
        vi.arbShaderAtomicCountersMaxFragmentAtomicCounterBuffers       = gl(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS);
        vi.arbShaderAtomicCountersMaxCombinedAtomicCounterBuffers       = gl(GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS);
        vi.arbShaderAtomicCountersMaxVertexAtomicCounters               = gl(GL_MAX_VERTEX_ATOMIC_COUNTERS);
        vi.arbShaderAtomicCountersMaxTessControlAtomicCounters          = gl(GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS);
        vi.arbShaderAtomicCountersMaxTessEvaluationAtomicCounters       = gl(GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS);
        vi.arbShaderAtomicCountersMaxGeometryAtomicCounters             = gl(GL_MAX_GEOMETRY_ATOMIC_COUNTERS);
        vi.arbShaderAtomicCountersMaxFragmentAtomicCounters             = gl(GL_MAX_FRAGMENT_ATOMIC_COUNTERS);
        vi.arbShaderAtomicCountersMaxCombinedAtomicCounters             = gl(GL_MAX_COMBINED_ATOMIC_COUNTERS);
        vi.arbShaderAtomicCountersMaxAtomicCounterBufferSize            = gl(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE);
        vi.arbShaderAtomicCountersMaxAtomicCounterBufferBindings        = gl(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS);
    }
    vi.arbShaderImageLoadStore = osg::isGLExtensionSupported(contextID, "GL_ARB_shader_image_load_store");
    if (vi.arbShaderImageLoadStore)
    {
        vi.arbShaderImageLoadStoreMaxImageUnits                           = gl(GL_MAX_IMAGE_UNITS);
        vi.arbShaderImageLoadStoreMaxCombinedImageUnitsAndFragmentOutputs = gl(GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS);
        vi.arbShaderImageLoadStoreMaxImageSamples                         = gl(GL_MAX_IMAGE_SAMPLES);
        vi.arbShaderImageLoadStoreMaxVertexImageUniforms                  = gl(GL_MAX_VERTEX_IMAGE_UNIFORMS);
        vi.arbShaderImageLoadStoreMaxTessControlImageUniforms             = gl(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS);
        vi.arbShaderImageLoadStoreMaxTessEvaluationImageUniforms          = gl(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS);
        vi.arbShaderImageLoadStoreMaxGeometryImageUniforms                = gl(GL_MAX_GEOMETRY_IMAGE_UNIFORMS);
        vi.arbShaderImageLoadStoreMaxFragmentImageUniforms                = gl(GL_MAX_FRAGMENT_IMAGE_UNIFORMS);
        vi.arbShaderImageLoadStoreMaxCombinedImageUniforms                = gl(GL_MAX_COMBINED_IMAGE_UNIFORMS);
    }
    if (vi.khrDebug)
    {
        vi.khrDebugMaxDebugGroupStackDepth = gl(GL_MAX_DEBUG_GROUP_STACK_DEPTH);
        vi.khrDebugMaxLabelLength          = gl(GL_MAX_LABEL_LENGTH);
        vi.khrDebugMaxDebugMessageLength   = gl(GL_MAX_DEBUG_MESSAGE_LENGTH);
        vi.khrDebugMaxDebugLoggedMessages  = gl(GL_MAX_DEBUG_LOGGED_MESSAGES);
    }
    vi.arbComputeShader = osg::isGLExtensionSupported(contextID, "GL_ARB_compute_shader");
    if (vi.arbComputeShader)
    {
        vi.arbComputeShaderMaxComputeUniformBlocks             = gl(GL_MAX_COMPUTE_UNIFORM_BLOCKS);
        vi.arbComputeShaderMaxComputeTextureImageUnits         = gl(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS);
        vi.arbComputeShaderMaxComputeImageUniforms             = gl(GL_MAX_COMPUTE_IMAGE_UNIFORMS);
        vi.arbComputeShaderMaxComputeSharedMemorySize          = gl(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE);
        vi.arbComputeShaderMaxComputeUniformComponents         = gl(GL_MAX_COMPUTE_UNIFORM_COMPONENTS);
        vi.arbComputeShaderMaxComputeAtomicCounterBuffers      = gl(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS);
        vi.arbComputeShaderMaxComputeAtomicCounters            = gl(GL_MAX_COMPUTE_ATOMIC_COUNTERS);
        vi.arbComputeShaderMaxCombinedComputeUniformComponents = gl(GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS);
        vi.arbComputeShaderMaxComputeLocalInvocations          = gl(GL_MAX_COMPUTE_LOCAL_INVOCATIONS);
        vi.arbComputeShaderMaxComputeWorkGroupCount            = gl(GL_MAX_COMPUTE_WORK_GROUP_COUNT);
        vi.arbComputeShaderMaxComputeWorkGroupSize             = gl(GL_MAX_COMPUTE_WORK_GROUP_SIZE);
    }
    vi.arbVertexAttribBinding = osg::isGLExtensionSupported(contextID, "GL_ARB_vertex_attrib_binding");
    if (vi.arbVertexAttribBinding)
    {
        vi.arbVertexAttribBindingMaxVertexAttribRelativeOffset = gl(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET);
        vi.arbVertexAttribBindingMaxVertexAttribBindings       = gl(GL_MAX_VERTEX_ATTRIB_BINDINGS);
    }
    vi.arbES3Compatibility = osg::isGLExtensionSupported(contextID, "GL_ARB_ES3_compatibility");
    if (vi.arbES3Compatibility)
        vi.arbES3CompatibilityMaxElementIndex = gl(GL_MAX_ELEMENT_INDEX);
    vi.arbExplicitUniformLocation = osg::isGLExtensionSupported(contextID, "GL_ARB_explicit_uniform_location");
    if (vi.arbExplicitUniformLocation)
        vi.arbExplicitUniformLocationMaxUniformLocations = gl(GL_MAX_UNIFORM_LOCATIONS);
    vi.arbFramebufferNoAttachments = osg::isGLExtensionSupported(contextID, "GL_ARB_framebuffer_no_attachments");
    if (vi.arbFramebufferNoAttachments)
    {
        vi.arbFramebufferNoAttachmentsMaxFramebufferWidth   = gl(GL_MAX_FRAMEBUFFER_WIDTH);
        vi.arbFramebufferNoAttachmentsMaxFramebufferHeight  = gl(GL_MAX_FRAMEBUFFER_HEIGHT);
        vi.arbFramebufferNoAttachmentsMaxFramebufferLayers  = gl(GL_MAX_FRAMEBUFFER_LAYERS);
        vi.arbFramebufferNoAttachmentsMaxFramebufferSamples = gl(GL_MAX_FRAMEBUFFER_SAMPLES);
    }
    vi.arbInternalformatQuery2 = osg::isGLExtensionSupported(contextID, "GL_ARB_internalformat_query2");
    if (vi.arbInternalformatQuery2)
    {
        vi.arbInternalformatQuery2MaxWidth              = gl(GL_MAX_WIDTH);
        vi.arbInternalformatQuery2MaxHeight             = gl(GL_MAX_HEIGHT);
        vi.arbInternalformatQuery2MaxDepth              = gl(GL_MAX_DEPTH);
        vi.arbInternalformatQuery2MaxLayers             = gl(GL_MAX_LAYERS);
        vi.arbInternalformatQuery2MaxCombinedDimensions = gl(GL_MAX_COMBINED_DIMENSIONS);
    }
    vi.arbProgramInterfaceQuery = osg::isGLExtensionSupported(contextID, "GL_ARB_program_interface_query");
    if (vi.arbProgramInterfaceQuery)
    {
        vi.arbProgramInterfaceQueryMaxNameLength               = gl(GL_MAX_NAME_LENGTH);
        vi.arbProgramInterfaceQueryMaxNumActiveVariables       = gl(GL_MAX_NUM_ACTIVE_VARIABLES);
        vi.arbProgramInterfaceQueryMaxNumCompatibleSubroutines = gl(GL_MAX_NUM_COMPATIBLE_SUBROUTINES);
    }
    vi.arbShaderStorageBufferObject = osg::isGLExtensionSupported(contextID, "GL_ARB_shader_storage_buffer_object");
    if (vi.arbShaderStorageBufferObject)
    {
        vi.arbShaderStorageBufferObjectMaxVertexShaderStorageBlocks         = gl(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS);
        vi.arbShaderStorageBufferObjectMaxGeometryShaderStorageBlocks       = gl(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS);
        vi.arbShaderStorageBufferObjectMaxTessControlShaderStorageBlocks    = gl(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS);
        vi.arbShaderStorageBufferObjectMaxTessEvaluationShaderStorageBlocks = gl(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS);
        vi.arbShaderStorageBufferObjectMaxFragmentShaderStorageBlocks       = gl(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS);
        vi.arbShaderStorageBufferObjectMaxComputeShaderStorageBlocks        = gl(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS);
        vi.arbShaderStorageBufferObjectMaxCombinedShaderStorageBlocks       = gl(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS);
        vi.arbShaderStorageBufferObjectMaxShaderStorageBufferBindings       = gl(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
        vi.arbShaderStorageBufferObjectMaxShaderStorageBlockSize            = gl(GL_MAX_SHADER_STORAGE_BLOCK_SIZE);
        vi.arbShaderStorageBufferObjectMaxCombinedShaderOutputResources     = gl(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES);
    }
    vi.extTexture3D = osg::isGLExtensionSupported(contextID, "GL_EXT_texture3D");
    if (vi.extTexture3D)
        vi.extTexture3DMax3DTextureSizeExt = gl(GL_MAX_3D_TEXTURE_SIZE_EXT);
    vi.extConvolution = osg::isGLExtensionSupported(contextID, "GL_EXT_convolution");
    if (vi.extConvolution)
    {
        vi.extConvolutionMaxConvolutionWidthExt  = gl(GL_MAX_CONVOLUTION_WIDTH_EXT);
        vi.extConvolutionMaxConvolutionHeightExt = gl(GL_MAX_CONVOLUTION_HEIGHT_EXT);
    }
    vi.sgiColorMatrix = osg::isGLExtensionSupported(contextID, "GL_SGI_color_matrix");
    if (vi.sgiColorMatrix)
        vi.sgiColorMatrixMaxColorMatrixStackDepthSGI = gl(GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI);
    vi.sgisTexture4D = osg::isGLExtensionSupported(contextID, "GL_SGIS_texture4D");
    if (vi.sgisTexture4D)
        vi.sgisTexture4DMax4DTextureSizeSGIS = gl(GL_MAX_4D_TEXTURE_SIZE_SGIS);
    vi.sgixClipmap = osg::isGLExtensionSupported(contextID, "GL_SGIX_clipmap");
    if (vi.sgixClipmap)
    {
        vi.sgixClipmapMaxClipmapDepthSGIX        = gl(GL_MAX_CLIPMAP_DEPTH_SGIX);
        vi.sgixClipmapMaxClipmapVirtualDepthSGIX = gl(GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX);
    }
    vi.sgixFramezoom = osg::isGLExtensionSupported(contextID, "GL_SGIX_framezoom");
    if (vi.sgixFramezoom)
        vi.sgixFramezoomMaxFramezoomFactorSGIX = gl(GL_MAX_FRAMEZOOM_FACTOR_SGIX);
    vi.sgixPolynomialFfd = osg::isGLExtensionSupported(contextID, "GL_SGIX_polynomial_ffd");
    if (vi.sgixPolynomialFfd)
        vi.sgixPolynomialFfdMaxDeformationOrderSGIX = gl(GL_MAX_DEFORMATION_ORDER_SGIX);
    vi.sgisFogFunction = osg::isGLExtensionSupported(contextID, "GL_SGIS_fog_function");
    if (vi.sgisFogFunction)
        vi.sgisFogFunctionMaxFogFuncPointsSGIS = gl(GL_MAX_FOG_FUNC_POINTS_SGIS);
    vi.pgiVertexHints = osg::isGLExtensionSupported(contextID, "GL_PGI_vertex_hints");
    if (vi.pgiVertexHints)
        vi.pgiVertexHintsMaxVertexHintPGI = gl(GL_MAX_VERTEX_HINT_PGI);
    vi.sgixFragmentLighting = osg::isGLExtensionSupported(contextID, "GL_SGIX_fragment_lighting");
    if (vi.sgixFragmentLighting)
    {
        vi.sgixFragmentLightingMaxFragmentLightsSGIX = gl(GL_MAX_FRAGMENT_LIGHTS_SGIX);
        vi.sgixFragmentLightingMaxActiveLightsSGIX   = gl(GL_MAX_ACTIVE_LIGHTS_SGIX);
    }
    vi.extDrawRangeElements = osg::isGLExtensionSupported(contextID, "GL_EXT_draw_range_elements");
    if (vi.extDrawRangeElements)
    {
        vi.extDrawRangeElementsMaxElementsVerticesExt = gl(GL_MAX_ELEMENTS_VERTICES_EXT);
        vi.extDrawRangeElementsMaxElementsIndicesExt  = gl(GL_MAX_ELEMENTS_INDICES_EXT);
    }
    vi.sgixAsyncPixel = osg::isGLExtensionSupported(contextID, "GL_SGIX_async_pixel");
    if (vi.sgixAsyncPixel)
    {
        vi.sgixAsyncPixelMaxAsyncTexImageSGIX   = gl(GL_MAX_ASYNC_TEX_IMAGE_SGIX);
        vi.sgixAsyncPixelMaxAsyncDrawPixelsSGIX = gl(GL_MAX_ASYNC_DRAW_PIXELS_SGIX);
        vi.sgixAsyncPixelMaxAsyncReadPixelsSGIX = gl(GL_MAX_ASYNC_READ_PIXELS_SGIX);
    }
    vi.sgixAsyncHistogram = osg::isGLExtensionSupported(contextID, "GL_SGIX_async_histogram");
    if (vi.sgixAsyncHistogram)
        vi.sgixAsyncHistogramMaxAsyncHistogramSGIX = gl(GL_MAX_ASYNC_HISTOGRAM_SGIX);
    vi.extPixelTransform = osg::isGLExtensionSupported(contextID, "GL_EXT_pixel_transform");
    if (vi.extPixelTransform)
        vi.extPixelTransformMaxPixelTransform2DStackDepthExt = gl(GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT);
    vi.extTextureCubeMap = osg::isGLExtensionSupported(contextID, "GL_EXT_texture_cube_map");
    if (vi.extTextureCubeMap)
        vi.extTextureCubeMapMaxCubeMapTextureSizeExt = gl(GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT);
    vi.extTextureLodBias = osg::isGLExtensionSupported(contextID, "GL_EXT_texture_lod_bias");
    if (vi.extTextureLodBias)
        vi.extTextureLodBiasMaxTextureLodBiasExt = gl(GL_MAX_TEXTURE_LOD_BIAS_EXT);
    vi.extTextureFilterAnisotropic = osg::isGLExtensionSupported(contextID, "GL_EXT_texture_filter_anisotropic");
    if (vi.extTextureFilterAnisotropic)
        vi.extTextureFilterAnisotropicMaxTextureMaxAnisotropyExt = gl(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT);
    vi.nvLightMaxExponent = osg::isGLExtensionSupported(contextID, "GL_NV_light_max_exponent");
    if (vi.nvLightMaxExponent)
    {
        vi.nvLightMaxExponentMaxShininessNV    = gl(GL_MAX_SHININESS_NV);
        vi.nvLightMaxExponentMaxSpotExponentNV = gl(GL_MAX_SPOT_EXPONENT_NV);
    }
    vi.nvVertexArrayRange = osg::isGLExtensionSupported(contextID, "GL_NV_vertex_array_range");
    if (vi.nvVertexArrayRange)
        vi.nvVertexArrayRangeMaxVertexArrayRangeElementNV = gl(GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV);
    vi.nvRegisterCombiners = osg::isGLExtensionSupported(contextID, "GL_NV_register_combiners");
    if (vi.nvRegisterCombiners)
        vi.nvRegisterCombinersMaxGeneralCombinersNV = gl(GL_MAX_GENERAL_COMBINERS_NV);
    vi.nvEvaluators = osg::isGLExtensionSupported(contextID, "GL_NV_evaluators");
    if (vi.nvEvaluators)
    {
        vi.nvEvaluatorsMaxMapTessellationNV   = gl(GL_MAX_MAP_TESSELLATION_NV);
        vi.nvEvaluatorsMaxRationalEvalOrderNV = gl(GL_MAX_RATIONAL_EVAL_ORDER_NV);
    }
    vi.nvTextureRectangle = osg::isGLExtensionSupported(contextID, "GL_NV_texture_rectangle");
    if (vi.nvTextureRectangle)
        vi.nvTextureRectangleMaxRectangleTextureSizeNV = gl(GL_MAX_RECTANGLE_TEXTURE_SIZE_NV);
    vi.nvVertexProgram = osg::isGLExtensionSupported(contextID, "GL_NV_vertex_program");
    if (vi.nvVertexProgram)
    {
        vi.nvVertexProgramMaxTrackMatrixStackDepthNV = gl(GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV);
        vi.nvVertexProgramMaxTrackMatricesNV         = gl(GL_MAX_TRACK_MATRICES_NV);
    }
    vi.atiPnTriangles = osg::isGLExtensionSupported(contextID, "GL_ATI_pn_triangles");
    if (vi.atiPnTriangles)
        vi.atiPnTrianglesMaxPnTrianglesTesselationLevelATI = gl(GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI);
    vi.extVertexShader = osg::isGLExtensionSupported(contextID, "GL_EXT_vertex_shader");
    if (vi.extVertexShader)
    {
        vi.extVertexShaderMaxVertexShaderInstructionsExt            = gl(GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT);
        vi.extVertexShaderMaxVertexShaderVariantsExt                = gl(GL_MAX_VERTEX_SHADER_VARIANTS_EXT);
        vi.extVertexShaderMaxVertexShaderInvariantsExt              = gl(GL_MAX_VERTEX_SHADER_INVARIANTS_EXT);
        vi.extVertexShaderMaxVertexShaderLocalConstantsExt          = gl(GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT);
        vi.extVertexShaderMaxVertexShaderLocalsExt                  = gl(GL_MAX_VERTEX_SHADER_LOCALS_EXT);
        vi.extVertexShaderMaxOptimizedVertexShaderInstructionsExt   = gl(GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT);
        vi.extVertexShaderMaxOptimizedVertexShaderVariantsExt       = gl(GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT);
        vi.extVertexShaderMaxOptimizedVertexShaderLocalConstantsExt = gl(GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT);
        vi.extVertexShaderMaxOptimizedVertexShaderInvariantsExt     = gl(GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT);
        vi.extVertexShaderMaxOptimizedVertexShaderLocalsExt         = gl(GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT);
    }
    vi.atiVertexStreams = osg::isGLExtensionSupported(contextID, "GL_ATI_vertex_streams");
    if (vi.atiVertexStreams)
        vi.atiVertexStreamsMaxVertexStreamsATI = gl(GL_MAX_VERTEX_STREAMS_ATI);
    vi.atiDrawBuffers = osg::isGLExtensionSupported(contextID, "GL_ATI_draw_buffers");
    if (vi.atiDrawBuffers)
        vi.atiDrawBuffersMaxDrawBuffersATI = gl(GL_MAX_DRAW_BUFFERS_ATI);
    vi.nvFragmentProgram = osg::isGLExtensionSupported(contextID, "GL_NV_fragment_program");
    if (vi.nvFragmentProgram)
    {
        vi.nvFragmentProgramMaxFragmentProgramLocalParametersNV = gl(GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV);
        vi.nvFragmentProgramMaxTextureCoordsNV                  = gl(GL_MAX_TEXTURE_COORDS_NV);
        vi.nvFragmentProgramMaxTextureImageUnitsNV              = gl(GL_MAX_TEXTURE_IMAGE_UNITS_NV);
    }
    vi.nvFragmentProgram2 = osg::isGLExtensionSupported(contextID, "GL_NV_fragment_program2");
    if (vi.nvFragmentProgram2)
    {
        vi.nvFragmentProgram2MaxProgramExecInstructionsNV = gl(GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV);
        vi.nvFragmentProgram2MaxProgramCallDepthNV        = gl(GL_MAX_PROGRAM_CALL_DEPTH_NV);
        vi.nvFragmentProgram2MaxProgramIfDepthNV          = gl(GL_MAX_PROGRAM_IF_DEPTH_NV);
        vi.nvFragmentProgram2MaxProgramLoopDepthNV        = gl(GL_MAX_PROGRAM_LOOP_DEPTH_NV);
        vi.nvFragmentProgram2MaxProgramLoopCountNV        = gl(GL_MAX_PROGRAM_LOOP_COUNT_NV);
    }
    vi.extFramebufferObject = osg::isGLExtensionSupported(contextID, "GL_EXT_framebuffer_object");
    if (vi.extFramebufferObject)
    {
        vi.extFramebufferObjectMaxRenderbufferSizeExt = gl(GL_MAX_RENDERBUFFER_SIZE_EXT);
        vi.extFramebufferObjectMaxColorAttachmentsExt = gl(GL_MAX_COLOR_ATTACHMENTS_EXT);
    }
    vi.extFramebufferMultisample = osg::isGLExtensionSupported(contextID, "GL_EXT_framebuffer_multisample");
    if (vi.extFramebufferMultisample)
        vi.extFramebufferMultisampleMaxSamplesExt = gl(GL_MAX_SAMPLES_EXT);
    vi.nvGpuProgram4 = osg::isGLExtensionSupported(contextID, "GL_NV_gpu_program4");
    if (vi.nvGpuProgram4)
    {
        vi.nvGpuProgram4MaxProgramAttribComponentsNV = gl(GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV);
        vi.nvGpuProgram4MaxProgramResultComponentsNV = gl(GL_MAX_PROGRAM_RESULT_COMPONENTS_NV);
        vi.nvGpuProgram4MaxProgramGenericAttribsNV   = gl(GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV);
        vi.nvGpuProgram4MaxProgramGenericResultsNV   = gl(GL_MAX_PROGRAM_GENERIC_RESULTS_NV);
    }
    vi.nvGeometryProgram4 = osg::isGLExtensionSupported(contextID, "GL_NV_geometry_program4");
    if (vi.nvGeometryProgram4)
    {
        vi.nvGeometryProgram4MaxProgramOutputVerticesNV        = gl(GL_MAX_PROGRAM_OUTPUT_VERTICES_NV);
        vi.nvGeometryProgram4MaxProgramTotalOutputComponentsNV = gl(GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV);
        vi.nvGeometryProgram4MaxGeometryTextureImageUnitsExt   = gl(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT);
    }
    vi.extGeometryShader4 = osg::isGLExtensionSupported(contextID, "GL_EXT_geometry_shader4");
    if (vi.extGeometryShader4)
    {
        vi.extGeometryShader4MaxGeometryVaryingComponentsExt     = gl(GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT);
        vi.extGeometryShader4MaxVertexVaryingComponentsExt       = gl(GL_MAX_VERTEX_VARYING_COMPONENTS_EXT);
        vi.extGeometryShader4MaxVaryingComponentsExt             = gl(GL_MAX_VARYING_COMPONENTS_EXT);
        vi.extGeometryShader4MaxGeometryUniformComponentsExt     = gl(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT);
        vi.extGeometryShader4MaxGeometryOutputVerticesExt        = gl(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT);
        vi.extGeometryShader4MaxGeometryTotalOutputComponentsExt = gl(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT);
    }
    vi.extTextureArray = osg::isGLExtensionSupported(contextID, "GL_EXT_texture_array");
    if (vi.extTextureArray)
        vi.extTextureArrayMaxArrayTextureLayersExt = gl(GL_MAX_ARRAY_TEXTURE_LAYERS_EXT);
    vi.extTextureBufferObject = osg::isGLExtensionSupported(contextID, "GL_EXT_texture_buffer_object");
    if (vi.extTextureBufferObject)
        vi.extTextureBufferObjectMaxTextureBufferSizeExt = gl(GL_MAX_TEXTURE_BUFFER_SIZE_EXT);
    vi.nvFramebufferMultisampleCoverage = osg::isGLExtensionSupported(contextID, "GL_NV_framebuffer_multisample_coverage");
    if (vi.nvFramebufferMultisampleCoverage)
        vi.nvFramebufferMultisampleCoverageMaxMultisampleCoverageModesNV = gl(GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV);
    vi.nvParameterBufferObject = osg::isGLExtensionSupported(contextID, "GL_NV_parameter_buffer_object");
    if (vi.nvParameterBufferObject)
    {
        vi.nvParameterBufferObjectMaxProgramParameterBufferBindingsNV = gl(GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV);
        vi.nvParameterBufferObjectMaxProgramParameterBufferSizeNV     = gl(GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV);
    }
    vi.nvTransformFeedback = osg::isGLExtensionSupported(contextID, "GL_NV_transform_feedback");
    if (vi.nvTransformFeedback)
    {
        vi.nvTransformFeedbackMaxTransformFeedbackSeparateComponentsNV    = gl(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV);
        vi.nvTransformFeedbackMaxTransformFeedbackInterleavedComponentsNV = gl(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV);
        vi.nvTransformFeedbackMaxTransformFeedbackSeparateAttribsNV       = gl(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV);
    }
    vi.extBindableUniform = osg::isGLExtensionSupported(contextID, "GL_EXT_bindable_uniform");
    if (vi.extBindableUniform)
    {
        vi.extBindableUniformMaxVertexBindableUniformsExt   = gl(GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT);
        vi.extBindableUniformMaxFragmentBindableUniformsExt = gl(GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT);
        vi.extBindableUniformMaxGeometryBindableUniformsExt = gl(GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT);
        vi.extBindableUniformMaxBindableUniformSizeExt      = gl(GL_MAX_BINDABLE_UNIFORM_SIZE_EXT);
    }
    vi.extTransformFeedback = osg::isGLExtensionSupported(contextID, "GL_EXT_transform_feedback");
    if (vi.extTransformFeedback)
    {
        vi.extTransformFeedbackMaxTransformFeedbackInterleavedComponentsExt = gl(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT);
        vi.extTransformFeedbackMaxTransformFeedbackSeparateAttribsExt       = gl(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT);
        vi.extTransformFeedbackMaxTransformFeedbackSeparateComponentsExt    = gl(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT);
    }
    vi.nvExplicitMultisample = osg::isGLExtensionSupported(contextID, "GL_NV_explicit_multisample");
    if (vi.nvExplicitMultisample)
        vi.nvExplicitMultisampleMaxSampleMaskWordsNV = gl(GL_MAX_SAMPLE_MASK_WORDS_NV);
    vi.nvShaderBufferLoad = osg::isGLExtensionSupported(contextID, "GL_NV_shader_buffer_load");
    if (vi.nvShaderBufferLoad)
        vi.nvShaderBufferLoadMaxShaderBufferAddressNV = gl(GL_MAX_SHADER_BUFFER_ADDRESS_NV);
    vi.extShaderImageLoadStore = osg::isGLExtensionSupported(contextID, "GL_EXT_shader_image_load_store");
    if (vi.extShaderImageLoadStore)
    {
        vi.extShaderImageLoadStoreMaxImageUnitsExt                           = gl(GL_MAX_IMAGE_UNITS_EXT);
        vi.extShaderImageLoadStoreMaxCombinedImageUnitsAndFragmentOutputsExt = gl(GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT);
        vi.extShaderImageLoadStoreMaxImageSamplesExt                         = gl(GL_MAX_IMAGE_SAMPLES_EXT);
    }
    vi.nvGpuProgram5 = osg::isGLExtensionSupported(contextID, "GL_NV_gpu_program5");
    if (vi.nvGpuProgram5)
    {
        vi.nvGpuProgram5MaxGeometryProgramInvocationsNV  = gl(GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV);
        vi.nvGpuProgram5MaxProgramSubroutineParametersNV = gl(GL_MAX_PROGRAM_SUBROUTINE_PARAMETERS_NV);
        vi.nvGpuProgram5MaxProgramSubroutineNumNV        = gl(GL_MAX_PROGRAM_SUBROUTINE_NUM_NV);
    }
    vi.nvTessellationProgram5 = osg::isGLExtensionSupported(contextID, "GL_NV_tessellation_program5");
    if (vi.nvTessellationProgram5)
        vi.nvTessellationProgram5MaxProgramPatchAttribsNV = gl(GL_MAX_PROGRAM_PATCH_ATTRIBS_NV);
    vi.amdDebugOutput = osg::isGLExtensionSupported(contextID, "GL_AMD_debug_output");
    if (vi.amdDebugOutput)
    {
        vi.amdDebugOutputMaxDebugMessageLengthAMD  = gl(GL_MAX_DEBUG_MESSAGE_LENGTH_AMD);
        vi.amdDebugOutputMaxDebugLoggedMessagesAMD = gl(GL_MAX_DEBUG_LOGGED_MESSAGES_AMD);
    }
    vi.amdSparseTexture = osg::isGLExtensionSupported(contextID, "GL_AMD_sparse_texture");
    if (vi.amdSparseTexture)
    {
        vi.amdSparseTextureMaxSparseTextureSizeAMD     = gl(GL_MAX_SPARSE_TEXTURE_SIZE_AMD);
        vi.amdSparseTextureMaxSparse3DTextureSizeAMD   = gl(GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD);
        vi.amdSparseTextureMaxSparseArrayTextureLayers = gl(GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS);
    }
    return vi;
}

} // namespace priv
} // namespace mjin2

